{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import keras\n",
    "\n",
    "from keras.layers import Dense\n",
    "from keras.models import Model\n",
    "\n",
    "import h5py\n",
    "\n",
    "import numpy as np\n",
    "import os\n",
    "\n",
    "from keras.models import Model\n",
    "from keras.layers import Input, Dense, Dropout, Flatten, GlobalAveragePooling2D, GlobalMaxPooling2D, BatchNormalization, Activation\n",
    "from keras import optimizers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### [Allowing GPU memory growth](https://www.tensorflow.org/programmers_guide/using_gpu#allowing_gpu_memory_growth)\n",
    "```\n",
    "...\\stream_executor\\cuda\\cuda_dnn.cc:371] could not create cudnn handle: CUDNN_STATUS_NOT_INITIALIZED\n",
    "...\\stream_executor\\cuda\\cuda_dnn.cc:375] error retrieving driver version: Unimplemented: kernel reported driver version not implemented on Windows\n",
    "...\\stream_executor\\cuda\\cuda_dnn.cc:338] could not destroy cudnn handle: CUDNN_STATUS_BAD_PARAM\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "from keras.backend.tensorflow_backend import set_session\n",
    "config = tf.ConfigProto()\n",
    "config.gpu_options.allow_growth = True\n",
    "set_session(tf.Session(config=config))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "ename": "KeyError",
     "evalue": "\"Unable to open object (object 'test_features' doesn't exist)\"",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyError\u001b[0m                                  Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-3-0032656a4b82>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      4\u001b[0m     \u001b[0mval_x\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'val_features'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m     \u001b[0mval_y\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'val_labels'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 6\u001b[1;33m     \u001b[0mtest_x\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'test_features'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32mh5py\\_objects.pyx\u001b[0m in \u001b[0;36mh5py._objects.with_phil.wrapper\u001b[1;34m()\u001b[0m\n",
      "\u001b[1;32mh5py\\_objects.pyx\u001b[0m in \u001b[0;36mh5py._objects.with_phil.wrapper\u001b[1;34m()\u001b[0m\n",
      "\u001b[1;32mC:\\Users\\chenwu\\Anaconda3\\lib\\site-packages\\h5py\\_hl\\group.py\u001b[0m in \u001b[0;36m__getitem__\u001b[1;34m(self, name)\u001b[0m\n\u001b[0;32m    175\u001b[0m                 \u001b[1;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Invalid HDF5 object reference\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    176\u001b[0m         \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 177\u001b[1;33m             \u001b[0moid\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mh5o\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mid\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_e\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlapl\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_lapl\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    178\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    179\u001b[0m         \u001b[0motype\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mh5i\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_type\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0moid\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mh5py\\_objects.pyx\u001b[0m in \u001b[0;36mh5py._objects.with_phil.wrapper\u001b[1;34m()\u001b[0m\n",
      "\u001b[1;32mh5py\\_objects.pyx\u001b[0m in \u001b[0;36mh5py._objects.with_phil.wrapper\u001b[1;34m()\u001b[0m\n",
      "\u001b[1;32mh5py\\h5o.pyx\u001b[0m in \u001b[0;36mh5py.h5o.open\u001b[1;34m()\u001b[0m\n",
      "\u001b[1;31mKeyError\u001b[0m: \"Unable to open object (object 'test_features' doesn't exist)\""
     ]
    }
   ],
   "source": [
    "with h5py.File('datasets/inception_resnet_v2.h5', 'r') as f:\n",
    "    train_x = np.array(f['train_features'])\n",
    "    train_y = np.array(f['train_labels'])\n",
    "    val_x = np.array(f['val_features'])\n",
    "    val_y = np.array(f['val_labels'])\n",
    "    test_x = np.array(f['test_features'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "with h5py.File('datasets/inception_resnet_v2_test.h5', 'r') as f:\n",
    "    test_x = np.array(f['test_features'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "inputs = Input(train_x.shape[1:])\n",
    "x = inputs\n",
    "x = GlobalAveragePooling2D()(x)\n",
    "x = Dense(256, activation='relu')(x)\n",
    "x = Dropout(.5)(x)\n",
    "y = Dense(120, activation='softmax')(x)\n",
    "\n",
    "model = Model(inputs=inputs, outputs=y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "input_1 (InputLayer)         (None, 8, 8, 1536)        0         \n",
      "_________________________________________________________________\n",
      "global_average_pooling2d_1 ( (None, 1536)              0         \n",
      "_________________________________________________________________\n",
      "dense_1 (Dense)              (None, 256)               393472    \n",
      "_________________________________________________________________\n",
      "dropout_1 (Dropout)          (None, 256)               0         \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 120)               30840     \n",
      "=================================================================\n",
      "Total params: 424,312\n",
      "Trainable params: 424,312\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "model.save_weights('empty_weights.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "model.compile(optimizer='adam',\n",
    "              loss='categorical_crossentropy',\n",
    "              metrics=['accuracy'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 8221 samples, validate on 2001 samples\n",
      "Epoch 1/1\n",
      "8221/8221 [==============================] - 6s 675us/step - loss: 0.4873 - acc: 0.8640 - val_loss: 0.3043 - val_acc: 0.9110\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x26a00133fd0>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.fit(\n",
    "    x=train_x,\n",
    "    y=train_y,\n",
    "    batch_size=32,\n",
    "    epochs=1,\n",
    "    validation_data=(val_x, val_y)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "model.load_weights('empty_weights.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "model.save_weights('good_weights.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 2001 images belonging to 120 classes.\n"
     ]
    }
   ],
   "source": [
    "from keras.applications.imagenet_utils import preprocess_input\n",
    "from keras.preprocessing import image\n",
    "\n",
    "def train_loader(path, shuffle=True, batch_size=32, target_size=(224,224), preprocessing_function=preprocess_input):\n",
    "    datagen = image.ImageDataGenerator(\n",
    "        preprocessing_function=preprocessing_function\n",
    "    )\n",
    "\n",
    "    return datagen.flow_from_directory(\n",
    "        path,\n",
    "        target_size=target_size,\n",
    "        batch_size=batch_size, \n",
    "        shuffle=shuffle,\n",
    "    )\n",
    "\n",
    "loader = train_loader('datasets/val')\n",
    "classes = list(loader.class_indices.keys())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "y_preds = model.predict(test_x, batch_size=32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 10357 images belonging to 1 classes.\n"
     ]
    }
   ],
   "source": [
    "test_loader = train_loader('datasets/test')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "images_id = [f[8:-4] for f in test_loader.filenames]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame(y_preds)\n",
    "\n",
    "df.columns = classes\n",
    "\n",
    "df.insert(0, 'id', images_id)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "df.to_csv('sub.gz', compression='gzip', index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
